package cc.verywell.pureblock.net;

import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

import cc.verywell.pureblock.log.Pblog;

/**
* 
* Copyright 2019 TanYaqiu
* @author TanYaqiu 
* @address flat 601
* @date 2019年3月14日 上午12:54:06
*/
abstract public class AbstractChannel implements Closeable {

	
	final private Object myAlias; //自我标识;
	public Object myAlias() {
		return myAlias;
	}
	public AbstractChannel(Object myAlias) {
		this.myAlias = myAlias;
	}
	
	protected AsynchronousSocketChannel channel;
	public AsynchronousSocketChannel getChannel() {
		return channel;
	}
	
	@Override
	public void close() {
		if(channel!=null && channel.isOpen()) {
			try {
				channel.shutdownInput();
			} catch (IOException e) {
				if(Pblog.IO)Pblog.IO("closing@",this,": ",e);
			}
			try {
				channel.shutdownOutput();
			} catch (IOException e) {
				if(Pblog.IO)Pblog.IO("closing@",this,": ",e);
			}
			try {
				channel.close();
			} catch (IOException e) {
				if(Pblog.IO)Pblog.IO("closing@",this,": ",e);
			}
		}
	}
	
	abstract protected void wrote(int result);
	abstract protected void wroteFailed(Throwable exc);
	final static protected CompletionHandler<Integer,AbstractChannel> WriteHandler = new CompletionHandler<Integer,AbstractChannel>(){
		@Override
		public void completed(Integer result, AbstractChannel attachment) {
			attachment.wrote(result);
		}
		@Override
		public void failed(Throwable exc, AbstractChannel attachment) {
			attachment.wroteFailed(exc);
		}
	};
	
	
	abstract protected void read(int result);
	abstract protected void readFailed(Throwable exc);
	final static protected CompletionHandler<Integer,AbstractChannel> ReadHandler = new CompletionHandler<Integer,AbstractChannel>(){
		@Override
		public void completed(Integer result, AbstractChannel attachment) {
			attachment.read(result);
		}
		@Override
		public void failed(Throwable exc, AbstractChannel attachment) {
			attachment.readFailed(exc);
		}
	};

	abstract public boolean isClient();
	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append(getClass().getSimpleName()).append("<def>");
		appendNoSessionToString(sb);
		return sb.toString();
	}
	protected void appendNoSessionToString(StringBuffer sb) {
		AsynchronousSocketChannel channel = getChannel();
		sb.append("[").append(myAlias()).append(isClient()?"->":"<-");
		if(channel!=null) {
			sb.append("(").append(Integer.toHexString(channel.hashCode())).append(")");
			try {
				sb.append(channel.getRemoteAddress() );
			} catch (IOException e) {
				sb.append(e.getLocalizedMessage());
			}
		}else{
			sb.append("noChannel");
		}
		sb.append("]").append(Integer.toHexString(this.hashCode()));
	}

}
